{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 动态编译"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 标准编程语言"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对于 **C** 语言，代码一般要先编译，再执行。\n",
    "\n",
    "    .c -> .exe"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 解释器语言"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "shell 脚本\n",
    "\n",
    "    .sh -> interpreter"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Byte Code 编译"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Python, Java** 等语言先将代码编译为 byte code（不是机器码），然后再处理：\n",
    "\n",
    "    .py -> .pyc -> interpreter"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## eval 函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    eval(statement, glob, local)\n",
    "\n",
    "使用 `eval` 函数动态执行代码，返回执行的值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = 1\n",
    "\n",
    "eval(\"a+1\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以接收明明空间参数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "local = dict(a=2)\n",
    "glob = {}\n",
    "eval(\"a+1\", glob, local)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里 `local` 中的 `a` 先被找到。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## exec 函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    exec(statement, glob, local)\n",
    "\n",
    "使用 `exec` 可以添加修改原有的变量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n"
     ]
    }
   ],
   "source": [
    "a = 1\n",
    "\n",
    "exec(\"b = a+1\")\n",
    "\n",
    "print b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'a': 2, 'b': 3}\n"
     ]
    }
   ],
   "source": [
    "local = dict(a=2)\n",
    "glob = {}\n",
    "exec(\"b = a+1\", glob, local)\n",
    "\n",
    "print local"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "执行之后，`b` 在 `local` 命名空间中。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 警告"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "动态执行的时候要注意，不要执行不信任的用户输入，因为它们拥有 `Python` 的全部权限。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## compile 函数生成 byte code"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    compile(str, filename, mode)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = 1\n",
    "c = compile(\"a+2\", \"\", 'eval')\n",
    "\n",
    "eval(c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = 1\n",
    "c = compile(\"b=a+2\", \"\", 'exec')\n",
    "\n",
    "exec(c)\n",
    "b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## abstract syntax trees"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import ast"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=Add(), right=Num(n=2)))\""
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tree = ast.parse(\"a+2\", \"\", \"eval\")\n",
    "\n",
    "ast.dump(tree)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "改变常数的值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=Add(), right=Num(n=3)))\""
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tree.body.right.n = 3\n",
    "\n",
    "ast.dump(tree)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = 1\n",
    "c = compile(tree, '', 'eval')\n",
    "\n",
    "eval(c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "安全的使用方法 `literal_eval` ，只支持基本值的操作："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[10.0, 2, True, 'foo']"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ast.literal_eval(\"[10.0, 2, True, 'foo']\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
